﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using System.Web;
using System.Web.Mvc;
using AZROLESLib;
using AzManContrib.MVC.Html.Behaviors;
using System.Web.Mvc.Html;

namespace AzManContrib.MVC.Html
{
    public static class TextBoxExtensions
    {
        /* 
         * Non generic with operation by name
         */
        public static MvcHtmlString TextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string operation)
        {
            return TextBoxFor(htmlHelper, expression, AzMan.Application.Operations.FindByName(operation));
        }

        public static MvcHtmlString TextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, string operation)
        {
            return TextBoxFor(htmlHelper, expression, htmlHelper, AzMan.Application.Operations.FindByName(operation));
        }

        public static MvcHtmlString TextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes, string operation)
        {
            return TextBoxFor(htmlHelper, expression, htmlHelper, AzMan.Application.Operations.FindByName(operation));
        }

        /* 
         * Non generic method, thus using AzMan.Defaults.UI.DenyiedBehavior 
         */
        public static MvcHtmlString TextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IAzOperation operation)
        {
            Func<HtmlHelper<TModel>, Expression<Func<TModel, TProperty>>, IAzOperation, MvcHtmlString> genMethod = TextBoxFor<TModel, TProperty, HiddenUIBehavior>;
            MethodInfo method = genMethod.Method.GetGenericMethodDefinition();
            MethodInfo generic = method.MakeGenericMethod(new[] { typeof(TModel), typeof(TProperty), AzMan.Defaults.UI.DenyiedBehavior });
            return generic.Invoke(htmlHelper, new object[] { htmlHelper, expression, operation }) as MvcHtmlString;
        }

        public static MvcHtmlString TextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, IAzOperation operation)
        {
            Func<HtmlHelper<TModel>, Expression<Func<TModel, TProperty>>, object, IAzOperation, MvcHtmlString> genMethod = TextBoxFor<TModel, TProperty, HiddenUIBehavior>;
            MethodInfo method = genMethod.Method.GetGenericMethodDefinition();
            MethodInfo generic = method.MakeGenericMethod(new[] { typeof(TModel), typeof(TProperty), AzMan.Defaults.UI.DenyiedBehavior });
            return generic.Invoke(htmlHelper, new [] { htmlHelper, expression, htmlAttributes, operation }) as MvcHtmlString;
        }

        public static MvcHtmlString TextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes, IAzOperation operation)
        {
            Func<HtmlHelper<TModel>, Expression<Func<TModel, TProperty>>, IDictionary<string, object>, IAzOperation, MvcHtmlString> genMethod = TextBoxFor<TModel, TProperty, HiddenUIBehavior>;
            MethodInfo method = genMethod.Method.GetGenericMethodDefinition();
            MethodInfo generic = method.MakeGenericMethod(new[] { typeof(TModel), typeof(TProperty), AzMan.Defaults.UI.DenyiedBehavior });
            return generic.Invoke(htmlHelper, new object[] { htmlHelper, expression, htmlAttributes, operation }) as MvcHtmlString;
        }


        /* 
         * Generic methods, thus you can provide an inhibition behavior.
         */
        public static MvcHtmlString TextBoxFor<TModel, TProperty, TBehavior>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IAzOperation operation)
            where TBehavior : IUIBehavior, new()
        {
            return htmlHelper.TextBoxFor<TModel, TProperty, TBehavior>(expression, null, operation);
        }

        public static MvcHtmlString TextBoxFor<TModel, TProperty, TBehavior>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, IAzOperation operation)
            where TBehavior : IUIBehavior, new()
        {
            return htmlHelper.TextBoxFor<TModel, TProperty, TBehavior>(expression, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes), operation);
        }

        public static MvcHtmlString TextBoxFor<TModel, TProperty, TBehavior>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes, IAzOperation operation)
            where TBehavior : IUIBehavior, new()
        {
            TBehavior behavior = new TBehavior();

            if (!HttpContext.Current.User.Can(operation))
            {
                if (!behavior.ShouldRender)
                    return MvcHtmlString.Empty;
                return htmlHelper.TextBoxFor(expression, behavior.GetHtmlAttributes(htmlAttributes));
            }
            return htmlHelper.TextBoxFor(expression, htmlAttributes);
        }

    }
}
